#include "hash_cmd.h"
#include "../common/v_common.h"

static int cmd_hash_to_lower(int c)
{
    if ((c >= 'A') && (c <= 'Z'))
        return c + ('a' - 'A');
    return c;
}

static uint32_t cmd_key_hash_func(const char* key)
{
    int tmp, c = *key;
    uint32_t seed = CMD_HASH;
    uint32_t hash = 0;
    
    while(*key) {
        tmp = cmd_hash_to_lower(c);
        hash = (hash ^ seed) + tmp;
        key++;
        c = *key;
    }
    return hash;
}

static bool cmd_key_equal_func(const char* key1, const char* key2)
{
    return strcmp(key1, key2) == 0 ? true : false;
}

void cmd_value_destroy_func(cmd_t* value)
{
    value = NULL;
    v_free(value);
}

bool cmd_hash_map_insert(hash_map* map, char* cmd, cmd_handler handler)
{
    bool ret = false;
    cmd_t* cmd_value = (cmd_t*)v_malloc(sizeof(cmd_t));
    if(cmd_value == NULL) {
        printk("new cmd insert errno\n");
        return false;
    }
    cmd_value->cmd = cmd;
    cmd_value->hash = cmd_key_hash_func(cmd);
    cmd_value->handler = handler;

    ret = bh_hash_map_insert(map, cmd, cmd_value);

    return ret;
}

void cmd_hash_parsing(cmd_hash_map_t* cmd_hash_map, char* cmd)
{
    cmd_t* cmd_value = (cmd_t*)bh_hash_map_find(cmd_hash_map->cmd_hash, cmd);
    if (cmd_value->handler == NULL) {
        printk("cmd:%s no register handler", cmd);
        return;
    }
    cmd_value->handler();
}

cmd_hash_map_t* cmd_hash_map_create(uint32_t size, bool use_lock, cmd_map_t* cmd_map, uint32_t map_size)
{
    cmd_hash_map_t* cmd_hash_map;
    cmd_hash_map = (cmd_hash_map_t*)v_malloc(sizeof(cmd_hash_map_t));
    if (cmd_hash_map == NULL) {
        printk("cmd_hash map create errno\n");
        return NULL;
    }

    cmd_hash_map->cmd_hash = bh_hash_map_create(size, use_lock, (hash_func)cmd_key_hash_func, 
                        (key_equal_func)cmd_key_equal_func, NULL, (value_destroy_func)cmd_value_destroy_func);
    if (cmd_hash_map->cmd_hash == NULL) {
        printk("cmd_hash create errno\n");
        v_free(cmd_hash_map);
        return NULL;
    }
    cmd_hash_map->cmd_map = cmd_map;

    if (cmd_map != NULL) {
        for (int i = 0; i < map_size; i++) {
            cmd_hash_map_insert(cmd_hash_map->cmd_hash, cmd_map[i].cmd, cmd_map[i].handler);
        }
    }
    
    return cmd_hash_map;
}

void cmd_hash_map_destroy(cmd_hash_map_t* cmd_hash_map)
{
    bh_hash_map_destroy(cmd_hash_map->cmd_hash);
    cmd_hash_map = NULL;
    v_free(cmd_hash_map);
}

void test1()
{
    printk("===test1===\r\n");
}

void test2()
{
    printk("===test2===\r\n");
}

